<template>
 <div>

    <el-switch
      v-model="draggable"
      active-text="开启节点拖动"
      inactive-text="关闭节点拖动">
    </el-switch>
    <el-button style="margin-left:20px;" type="danger" icon="el-icon-delete" @click="deleteSelect">批量删除</el-button>
    <el-button type="primary" @click="savaNodeSort">节点拖动保存</el-button>
     <!-- 树形组件 -->
     <el-tree
      class="mycss"
      :data="categorys"
      show-checkbox
      node-key="catId"
      :props="defaultProps"
      :draggable="draggable"
      :allow-drop="allowDrop"
      :default-expanded-keys="expandedKeys"
      ref="tree"
      @node-drop="nodeDrop" 
      :expand-on-click-node="nodeActive">
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button
            v-if="data.catLevel != 3"
            type="text"
            size="mini"
            @click="() => append(node,data)">
            添加
          </el-button>

          <el-button
            type="text"
            size="mini"
            @click="() => edit(node,data)">
            修改
          </el-button>

          <el-button
            v-if="node.childNodes.length == 0"
            type="text"
            size="mini"
            @click="() => remove(node, data)">
            删除
          </el-button>
        </span>
      </span>
    </el-tree>

  <!-- 弹窗组件 -->
  <CategoryDialog :flag="openDialog" @close="dialogClose" :pData="pData" @sonData="sonResData" />
 </div>
</template>

<!--
TODO
不发送请求添加节点和修改节点有数据问题（多人同时使用,该项目中的pData.node当前节点数据不是最新的）正确的应该是先发送请求
查到当前节点数据，然后传给子组件，自己测试使用不修改
-->
<script>

 import CategoryDialog from "@/components/dialog/categoryDialog.vue";
  import {uniqueArr} from "@/utils/myutils";

 export default {
   name: '',
   props: {
   },
   components: {
     CategoryDialog
   },
   data () {
      return {
        //最大深度，该案例中没有使用
        maxNodeLevel:0,
        //控制是否开启节点拖拽功能
        draggable:false,
        //保存更新拖动的节点信息
        updateCategorys:[],
        //保存添加的节点信息
        categorys: [],
        //控制弹窗的状态
        openDialog:false,
        //控制是否展开节点
        nodeActive:false,
        //保存要传递给子组件（弹窗）的数据
        pData:{},
        //保存子组件回调的数据
        sonCallback:{},
        //展开节点
        expandedKeys:[],
        //默认显示的名称
        defaultProps: {
          children: 'children',
          label: 'name'
        }
      }
    },

   methods: {
     //关闭弹窗回调
      dialogClose(closeData){
        this.openDialog = closeData;
      },

      //子组件CategoryDialog回调回来的参数
      sonResData(res){
        this.sonCallback = res;
      },

      //添加方法时弹出弹窗并传值给子组件CategoryDialog
      append(node, data) {
        this.openDialog = true;
        this.pData = {
          type:'add',
          node:node
        };
      },

      //修改时弹出并传值给子组件
      edit(node,data){
        this.openDialog = true;
        this.pData = {
          type:'edit',
          node:node
        };
      },

      //是否允许拖动
      allowDrop(draggingNode, dropNode, type){
        console.log(dropNode,type);
        //最大深度
        let deep = this.countNodeLevel(draggingNode);
        //判断是否有子节点
        if(draggingNode.childNodes && draggingNode.childNodes.length>0){
          //有子节点的情况要根据最大深度与目标节点层级判断是否可以放入
          if(type=='inner'){
            console.log('inner'+(deep+dropNode.level));
            return (deep+dropNode.level) <= 3;
          }else{
            // console.log('b,a'+(deep+dropNode.parent.level));
            return (deep+dropNode.parent.level) <= 3;
          }
        }else{
          //没有子节点的情况，只要不是放入规定的最大级别就可以随意拖动
          if(type=='inner'){
            return (draggingNode.level != 3 && draggingNode.level != 3);
          }else{
            return true;
          }
        }
      },

      //最大深度=(找到所有子节点最深级别-当前节点的级别)+1(老师使用)
      countNodeLevel(node){
        let childNode = node.childNodes;
        if(childNode && childNode.length>0){
          for(let i=0; i<childNode.length; i++){
            if(childNode[i].level > this.maxNodeLevel){
              this.maxNodeLevel = childNode[i].level;
            }
            this.countNodeLevel(childNode[i]);
          }
        }
        return  (this.maxNodeLevel - node.level)+1;
      },
      
      //节点拖拽成功完成时触发的事件
      nodeDrop(node,dropNode,type,ev){
        let pid = '';
        let silbingNode = [];
        if(type=='before' || type=='after'){
          pid = dropNode.data.parentCid;
          silbingNode = dropNode.parent.childNodes;
        }else{
          pid = dropNode.data.catId;
          silbingNode = dropNode.childNodes;
        }
        //遍历所有兄弟节点的值，将需要更新的数据装入数组中
        for(let i=0; i<silbingNode.length; i++){
          //如果遍历的是当前节点
          if(node.data.catId == silbingNode[i].data.catId){
            //若当前节点的层级发生变化，当前节点下的层级发生改变
            if(silbingNode[i].level != node.data.catLevel){
              this.updateChildNodeLevel(silbingNode[i]);
            }
            
            this.updateCategorys.push({
              catId:silbingNode[i].data.catId,
              sort:i,
              parentCid:pid,
              catLevel:silbingNode[i].level
            });
          }else{
            this.updateCategorys.push({
              catId:silbingNode[i].data.catId,
              sort:i,
            });
          }
          
        }

        console.log(this.updateCategorys);
      },

      //更新子节点的级别
      updateChildNodeLevel(node){
        if(node.childNodes && node.childNodes.length > 0){
          for(let i=0; i<node.childNodes.length; i++){
            this.updateCategorys.push({
              catId:node.childNodes[i].data.catId,
              catLevel:node.childNodes[i].level
            });

            this.updateChildNodeLevel(node.childNodes[i]);
          }
        }
      },



      //发送请求保存排序的节点
      savaNodeSort(){
        //提交时进行数据去重
        this.updateCategorys = uniqueArr(this.updateCategorys);
        this.$http({
            url: this.$http.adornUrl('/product/category/update/sort'),
            method: 'post',
            data:this.updateCategorys
         }).then((res) => {
           let {code} = res.data;
           if(code == 0){
              this.$message({
                type: 'success',
                message: '节点排序成功!'
              });
           }
           this.getCategoryList();
         }).catch(()=>{});
      },

      //发送请求删除选中的节点
      deleteSelect(node, data){
        let checkNodesData = this.$refs.tree.getCheckedNodes();
        checkNodesData = checkNodesData.map(item=>item.catId);
        // console.log(checkNodesData)
        this.remove(node,data,checkNodesData)
      },

      //发送请求删除数据
      remove(node, data, ...args) {
        this.$confirm('确定要删除该吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
        let removeData = [];
        args.length == 0 ?  removeData = [data.catId] :  removeData =  args[0];
          //发送请求删除数据
          this.$http({
                url: this.$http.adornUrl('/product/category/delete'),
                method: 'delete',
                data:removeData
            }).then((result) => {
              let {catids,code} = result.data;
              //删除成功
              if(code == 0){
                //  //找到当前节点
                // let parent = node.parent;
                // let children = parent.data.children || parent.data;
                // let index = children.findIndex(d => d.catId == catids[0]);
                // //移除节点
                // children.splice(index, 1);
                this.getCategoryList();
                // this.expandedKeys = [node.parent.data.catId];
                //给出提示
                this.$message({
                  type: 'success',
                  message: '删除成功!'
                });
              }

            }).cathc(()=>{});

         
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });          
        });
        // console.log(data);


      },


      //获取所有节点信息API
      getCategoryList () {
            this.$http({
                url: this.$http.adornUrl('/product/category/tree/list'),
                method: 'get',
            }).then(({data}) => {
                this.categorys = data.data;
            })
        },


   },
   mounted() {

   },
   watch: {
      // $route(to,from){
      //   if(to.path == "/product-category"){
      //     this.getCategoryList();
      //   }
      // }
   },
   computed: {

   },
   
   created(){
        this.getCategoryList();
   }

 }
</script>

<style scoped lang='scss'>
  .mycss{
    margin-top:15px;
  }
</style>